package com.tangruojie.exception;

import com.tangruojie.domain.ResponseCode;
import com.tangruojie.domain.ResponseResult;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * URL 级：UnauthenticatedHandler，UnauthorizedHandler
     * 方法级：handleAuthenticationException，handleAccessDeniedException
     */

    /**
     * 认证异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(AuthenticationException.class)
    public ResponseResult handleAuthenticationException(AuthenticationException e) {
        System.out.println("UNAUTHENTICATED");
        return new ResponseResult(
                ResponseCode.UNAUTHENTICATED,
                "未认证",
                null
        );
    }

    /**
     * 权限异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseResult handleAccessDeniedException(AccessDeniedException e) {
        System.out.println("UNAUTHORIZED");
        return new ResponseResult(
                ResponseCode.UNAUTHORIZED,
                "无权限",
                null
        );
    }

    /**
     * 统一异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public ResponseResult handle(Exception e) {
        return new ResponseResult(
                HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                e.getMessage(),
                null
        );
    }

}
/**
 * 1. Spring Security 异常处理器
 * 你配置的这两个处理器：
 * AuthenticationEntryPoint
 * 触发条件：请求需要认证但用户未认证（没有 token、token 过期、上下文中无认证对象）。
 * 返回：一般 401 Unauthorized。
 * AccessDeniedHandler
 * 触发条件：用户已认证，但访问了权限不足的资源（比如接口要求 ADMIN，你只有 USER）。
 * 返回：一般 403 Forbidden。
 * 👉 这两个处理器在 Spring Security 过滤器链里生效，拦截的是认证/授权阶段的异常。
 * 2. 全局异常处理器（@RestControllerAdvice + @ExceptionHandler）
 * 生效范围：Controller 层及其以下代码抛出的异常。
 * 触发条件：
 * 业务逻辑异常（比如 NullPointerException、IllegalArgumentException）；
 * 你自己 throw new BizException("xxx")；
 * 数据库异常、IO 异常等。
 * 返回：你定义的 JSON（通常是统一响应格式）。
 * 👉 全局异常处理器属于 Spring MVC 处理链，Security 在这之前就已经对认证/授权做了处理。
 * 3. 谁先拦截？
 * 认证/授权异常（AuthenticationException / AccessDeniedException） → 优先由 Security 的 exceptionHandling 配置拦截，不会进入全局异常处理器。
 * 业务逻辑异常（RuntimeException、BizException 等） → 不经过 Security，由全局异常处理器捕获。
 * 因此，两者不冲突，各司其职。
 */